#include "my_nvs.h"
#include "my_common.h"

#include <string.h>

#include "esp_mac.h"
#include "esp_log.h"
#include "nvs_flash.h"

// 持久化存储信息，命名空间
#define MY_NVS_NAMESPACE "esp32c3_light"

#define MY_NVS_KEY_WIFI_STATE "wifi_state"
#define MY_NVS_KEY_MQTT_STATE "mqtt_state"

#define MY_NVS_KEY_MQTT_URI "mqtt_uri"
#define MY_NVS_KEY_MQTT_SUB_TOPIC "mqtt_sub_topic"
#define MY_NVS_KEY_MQTT_PUB_TOPIC "mqtt_pub_topic"
#define MY_NVS_KEY_MQTT_USER "mqtt_user"
#define MY_NVS_KEY_MQTT_PASSWORD "mqtt_password"

static const char *TAG = "MY_NVS";
static char my_mac[13] = {0};

static void get_mac_str()
{
    uint8_t mac[6];
    esp_read_mac(mac, ESP_MAC_WIFI_STA);
    sprintf(my_mac, "%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    ESP_LOGI(TAG, "mac:%s", my_mac);
}

// 初始化nvs
void init_nvs(void)
{
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
    get_mac_str();
}

bool is_wifi_configured(void)
{
    nvs_handle_t nvs_handle;
    ESP_ERROR_CHECK(nvs_open(MY_NVS_NAMESPACE, NVS_READONLY, &nvs_handle));
    int8_t wifi_config_flag = 0;
    esp_err_t ret = nvs_get_i8(nvs_handle, MY_NVS_KEY_WIFI_STATE, &wifi_config_flag);
    if (ret != ESP_OK)
    {
        ESP_LOGI(TAG, "wifi_config_flag not found");
        wifi_config_flag = 0;
    }
    nvs_close(nvs_handle);
    return wifi_config_flag == 0 ? false : true;
}

void set_wifi_configured(void)
{
    nvs_handle_t nvs_handle;
    ESP_ERROR_CHECK(nvs_open(MY_NVS_NAMESPACE, NVS_READWRITE, &nvs_handle));
    ESP_ERROR_CHECK(nvs_set_i8(nvs_handle, MY_NVS_KEY_WIFI_STATE, 1));
    ESP_ERROR_CHECK(nvs_commit(nvs_handle));
    nvs_close(nvs_handle);
}

bool is_mqtt_configured(void)
{
    nvs_handle_t nvs_handle;
    ESP_ERROR_CHECK(nvs_open(MY_NVS_NAMESPACE, NVS_READONLY, &nvs_handle));
    int8_t config_flag = 0;
    esp_err_t ret = nvs_get_i8(nvs_handle, MY_NVS_KEY_MQTT_STATE, &config_flag);
    if (ret != ESP_OK)
    {
        ESP_LOGI(TAG, "mqtt_config_flag not found");
        config_flag = 0;
    }
    nvs_close(nvs_handle);
    return config_flag == 0 ? false : true;
}

void set_mqtt_configured(void)
{
    nvs_handle_t nvs_handle;
    ESP_ERROR_CHECK(nvs_open(MY_NVS_NAMESPACE, NVS_READWRITE, &nvs_handle));
    ESP_ERROR_CHECK(nvs_set_i8(nvs_handle, MY_NVS_KEY_MQTT_STATE, 1));
    ESP_ERROR_CHECK(nvs_commit(nvs_handle));
    nvs_close(nvs_handle);
}

void clear_all_configured_flag()
{
    nvs_handle_t nvs_handle;
    ESP_ERROR_CHECK(nvs_open(MY_NVS_NAMESPACE, NVS_READWRITE, &nvs_handle));
    ESP_ERROR_CHECK(nvs_set_i8(nvs_handle, MY_NVS_KEY_WIFI_STATE, 0));
    ESP_ERROR_CHECK(nvs_set_i8(nvs_handle, MY_NVS_KEY_MQTT_STATE, 0));
    ESP_ERROR_CHECK(nvs_commit(nvs_handle));
    nvs_close(nvs_handle);
}

void persist_mqtt_uri(char *mqtt_uri)
{
    nvs_handle_t nvs_handle;
    ESP_ERROR_CHECK(nvs_open(MY_NVS_NAMESPACE, NVS_READWRITE, &nvs_handle));
    ESP_ERROR_CHECK(nvs_set_str(nvs_handle, MY_NVS_KEY_MQTT_URI, mqtt_uri));
    nvs_commit(nvs_handle);
    nvs_close(nvs_handle);
}

void query_mqtt_uri(char *mqtt_uri)
{
    nvs_handle_t nvs_handle;
    ESP_ERROR_CHECK(nvs_open(MY_NVS_NAMESPACE, NVS_READONLY, &nvs_handle));
    size_t required_size;
    ESP_ERROR_CHECK(nvs_get_str(nvs_handle, MY_NVS_KEY_MQTT_URI, NULL, &required_size));
    ESP_ERROR_CHECK(nvs_get_str(nvs_handle, MY_NVS_KEY_MQTT_URI, mqtt_uri, &required_size));
    nvs_close(nvs_handle);
}

/**
 * @brief 获取MQTT配置主题
 */
void query_mqtt_config_topic(char *topic)
{
    strcpy(topic, MQTT_CONFIG_TOPIC_PREFIX);
    strcat(topic, my_mac);
}

void persist_mqtt_topic_user_password(char *topic, char *username, char *password)
{
    char mqtt_sub_topic[MQTT_TOPIC_LEN] = {0};
    strcpy(mqtt_sub_topic, topic);
    if (topic[strlen(topic) - 1] != '/')
    {
        strcat(mqtt_sub_topic, "/");
    }
    strcat(mqtt_sub_topic, my_mac);
    strcat(mqtt_sub_topic, "/cmd");

    char mqtt_pub_topic[MQTT_TOPIC_LEN] = {0};
    strcpy(mqtt_pub_topic, topic);
    strcat(mqtt_pub_topic, "/");
    strcat(mqtt_pub_topic, my_mac);
    strcat(mqtt_pub_topic, "/attr");

    nvs_handle_t nvs_handle;
    ESP_ERROR_CHECK(nvs_open(MY_NVS_NAMESPACE, NVS_READWRITE, &nvs_handle));
    ESP_ERROR_CHECK(nvs_set_i8(nvs_handle, MY_NVS_KEY_MQTT_STATE, 1));
    ESP_ERROR_CHECK(nvs_set_str(nvs_handle, MY_NVS_KEY_MQTT_SUB_TOPIC, mqtt_sub_topic));
    ESP_ERROR_CHECK(nvs_set_str(nvs_handle, MY_NVS_KEY_MQTT_PUB_TOPIC, mqtt_pub_topic));
    ESP_ERROR_CHECK(nvs_set_str(nvs_handle, MY_NVS_KEY_MQTT_USER, username));
    ESP_ERROR_CHECK(nvs_set_str(nvs_handle, MY_NVS_KEY_MQTT_PASSWORD, password));
    nvs_commit(nvs_handle);
    nvs_close(nvs_handle);
}

void query_mqtt_sub_topic(char *topic)
{
    nvs_handle_t nvs_handle;
    ESP_ERROR_CHECK(nvs_open(MY_NVS_NAMESPACE, NVS_READONLY, &nvs_handle));
    size_t required_size;
    ESP_ERROR_CHECK(nvs_get_str(nvs_handle, MY_NVS_KEY_MQTT_SUB_TOPIC, NULL, &required_size));
    ESP_ERROR_CHECK(nvs_get_str(nvs_handle, MY_NVS_KEY_MQTT_SUB_TOPIC, topic, &required_size));
    nvs_close(nvs_handle);
}

void query_mqtt_pub_topic(char *topic)
{
    nvs_handle_t nvs_handle;
    ESP_ERROR_CHECK(nvs_open(MY_NVS_NAMESPACE, NVS_READONLY, &nvs_handle));
    size_t required_size;
    ESP_ERROR_CHECK(nvs_get_str(nvs_handle, MY_NVS_KEY_MQTT_PUB_TOPIC, NULL, &required_size));
    ESP_ERROR_CHECK(nvs_get_str(nvs_handle, MY_NVS_KEY_MQTT_PUB_TOPIC, topic, &required_size));
    nvs_close(nvs_handle);
}

void query_mqtt_sub_pub_topic(char *sub_topic, char *pub_topic)
{
    nvs_handle_t nvs_handle;
    ESP_ERROR_CHECK(nvs_open(MY_NVS_NAMESPACE, NVS_READONLY, &nvs_handle));
    size_t required_size;
    ESP_ERROR_CHECK(nvs_get_str(nvs_handle, MY_NVS_KEY_MQTT_SUB_TOPIC, NULL, &required_size));
    ESP_ERROR_CHECK(nvs_get_str(nvs_handle, MY_NVS_KEY_MQTT_SUB_TOPIC, sub_topic, &required_size));

    ESP_ERROR_CHECK(nvs_get_str(nvs_handle, MY_NVS_KEY_MQTT_PUB_TOPIC, NULL, &required_size));
    ESP_ERROR_CHECK(nvs_get_str(nvs_handle, MY_NVS_KEY_MQTT_PUB_TOPIC, pub_topic, &required_size));
    nvs_close(nvs_handle);
}

void query_mqtt_username_password(char *username, char *password)
{
    nvs_handle_t nvs_handle;
    ESP_ERROR_CHECK(nvs_open(MY_NVS_NAMESPACE, NVS_READONLY, &nvs_handle));
    size_t required_size;
    ESP_ERROR_CHECK(nvs_get_str(nvs_handle, MY_NVS_KEY_MQTT_USER, NULL, &required_size));
    ESP_ERROR_CHECK(nvs_get_str(nvs_handle, MY_NVS_KEY_MQTT_USER, username, &required_size));

    ESP_ERROR_CHECK(nvs_get_str(nvs_handle, MY_NVS_KEY_MQTT_PASSWORD, NULL, &required_size));
    ESP_ERROR_CHECK(nvs_get_str(nvs_handle, MY_NVS_KEY_MQTT_PASSWORD, password, &required_size));
    nvs_close(nvs_handle);
}